"""笔记分享模块的数据模型

定义笔记分享相关的数据模型，包括分享链接、访问记录、评论等。
"""

import uuid
import secrets
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth import get_user_model
from django.core.validators import MinLengthValidator
from django.utils import timezone
from datetime import timedelta

User = get_user_model()


class SharedFolder(models.Model):
    """共享文件夹模型
    
    管理文件夹的分享设置和权限。
    """
    
    # 分享权限选择
    PERMISSION_CHOICES = [
        ('view', _('仅查看')),
        ('comment', _('查看和评论')),
        ('edit', _('查看和编辑')),
    ]
    
    # 分享范围选择
    SCOPE_CHOICES = [
        ('public', _('公开')),
        ('link', _('知道链接的人')),
        ('private', _('指定用户')),
    ]
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('分享ID')
    )
    
    # 关联文件夹（分类）
    category = models.ForeignKey(
        'notes.Category',
        on_delete=models.CASCADE,
        related_name='shares',
        verbose_name=_('文件夹')
    )
    
    # 分享者
    shared_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='shared_folders',
        verbose_name=_('分享者')
    )
    
    # 分享设置
    share_token = models.CharField(
        _('分享令牌'),
        max_length=32,
        unique=True,
        help_text=_('用于访问分享文件夹的唯一令牌')
    )
    
    title = models.CharField(
        _('分享标题'),
        max_length=200,
        help_text=_('分享时显示的标题')
    )
    
    description = models.TextField(
        _('分享描述'),
        max_length=500,
        blank=True,
        help_text=_('分享的描述信息')
    )
    
    permission = models.CharField(
        _('访问权限'),
        max_length=20,
        choices=PERMISSION_CHOICES,
        default='view',
        help_text=_('访问者的权限级别')
    )
    
    scope = models.CharField(
        _('分享范围'),
        max_length=20,
        choices=SCOPE_CHOICES,
        default='link',
        help_text=_('分享的可见范围')
    )
    
    # 访问控制
    password = models.CharField(
        _('访问密码'),
        max_length=128,
        blank=True,
        help_text=_('访问分享文件夹所需的密码')
    )
    
    max_views = models.PositiveIntegerField(
        _('最大访问次数'),
        null=True,
        blank=True,
        help_text=_('限制最大访问次数，为空表示不限制')
    )
    
    # 有效期设置
    expires_at = models.DateTimeField(
        _('过期时间'),
        null=True,
        blank=True,
        help_text=_('分享链接的过期时间')
    )
    
    # 状态
    is_active = models.BooleanField(
        _('是否激活'),
        default=True,
        help_text=_('分享是否处于激活状态')
    )
    
    # 统计信息
    view_count = models.PositiveIntegerField(
        _('访问次数'),
        default=0,
        help_text=_('分享被访问的次数')
    )
    
    unique_visitors = models.PositiveIntegerField(
        _('独立访客数'),
        default=0,
        help_text=_('独立访客的数量')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    updated_at = models.DateTimeField(
        _('更新时间'),
        auto_now=True
    )
    
    class Meta:
        verbose_name = _('共享文件夹')
        verbose_name_plural = _('共享文件夹')
        db_table = 'shared_folder'
        ordering = ['-created_at']
        unique_together = [['category', 'shared_by']]
        indexes = [
            models.Index(fields=['shared_by', '-created_at']),
            models.Index(fields=['share_token']),
            models.Index(fields=['is_active', '-created_at']),
        ]
    
    def __str__(self):
        """返回共享文件夹的字符串表示"""
        return f"{self.title} - {self.category.name}"
    
    def save(self, *args, **kwargs):
        """保存时自动生成分享令牌"""
        if not self.share_token:
            self.share_token = secrets.token_urlsafe(24)
        if not self.title:
            self.title = self.category.name
        super().save(*args, **kwargs)
    
    @property
    def share_url(self):
        """获取分享链接URL"""
        return f"/share/folder/{self.share_token}"
    
    @property
    def is_expired(self):
        """检查分享是否已过期"""
        if self.expires_at:
            return timezone.now() > self.expires_at
        return False
    
    @property
    def is_view_limit_reached(self):
        """检查是否达到访问次数限制"""
        if self.max_views:
            return self.view_count >= self.max_views
        return False
    
    def can_access(self):
        """检查分享是否可以访问"""
        return (
            self.is_active and
            not self.is_expired and
            not self.is_view_limit_reached
        )
    
    def increment_view_count(self, is_unique_visitor=False):
        """增加访问次数"""
        self.view_count += 1
        if is_unique_visitor:
            self.unique_visitors += 1
        self.save(update_fields=['view_count', 'unique_visitors'])


class SharedNote(models.Model):
    """共享笔记模型
    
    管理笔记的分享设置和权限。
    """
    
    # 分享权限选择
    PERMISSION_CHOICES = [
        ('view', _('仅查看')),
        ('comment', _('查看和评论')),
        ('edit', _('查看和编辑')),
    ]
    
    # 分享范围选择
    SCOPE_CHOICES = [
        ('public', _('公开')),
        ('link', _('知道链接的人')),
        ('private', _('指定用户')),
    ]
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('分享ID')
    )
    
    # 关联笔记
    note = models.ForeignKey(
        'notes.Note',
        on_delete=models.CASCADE,
        related_name='shares',
        verbose_name=_('笔记')
    )
    
    # 分享者
    shared_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='shared_notes',
        verbose_name=_('分享者')
    )
    
    # 分享设置
    share_token = models.CharField(
        _('分享令牌'),
        max_length=32,
        unique=True,
        help_text=_('用于访问分享笔记的唯一令牌')
    )
    
    title = models.CharField(
        _('分享标题'),
        max_length=200,
        help_text=_('分享时显示的标题')
    )
    
    description = models.TextField(
        _('分享描述'),
        max_length=500,
        blank=True,
        help_text=_('分享的描述信息')
    )
    
    permission = models.CharField(
        _('访问权限'),
        max_length=20,
        choices=PERMISSION_CHOICES,
        default='view',
        help_text=_('访问者的权限级别')
    )
    
    scope = models.CharField(
        _('分享范围'),
        max_length=20,
        choices=SCOPE_CHOICES,
        default='link',
        help_text=_('分享的可见范围')
    )
    
    # 访问控制
    password = models.CharField(
        _('访问密码'),
        max_length=128,
        blank=True,
        help_text=_('访问分享笔记所需的密码')
    )
    
    max_views = models.PositiveIntegerField(
        _('最大访问次数'),
        null=True,
        blank=True,
        help_text=_('限制最大访问次数，为空表示不限制')
    )
    
    # 有效期设置
    expires_at = models.DateTimeField(
        _('过期时间'),
        null=True,
        blank=True,
        help_text=_('分享链接的过期时间')
    )
    
    # 状态
    is_active = models.BooleanField(
        _('是否激活'),
        default=True,
        help_text=_('分享是否处于激活状态')
    )
    
    # 统计信息
    view_count = models.PositiveIntegerField(
        _('访问次数'),
        default=0,
        help_text=_('分享被访问的次数')
    )
    
    unique_visitors = models.PositiveIntegerField(
        _('独立访客数'),
        default=0,
        help_text=_('独立访客的数量')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    updated_at = models.DateTimeField(
        _('更新时间'),
        auto_now=True
    )
    
    last_accessed_at = models.DateTimeField(
        _('最后访问时间'),
        null=True,
        blank=True
    )
    
    class Meta:
        verbose_name = _('共享笔记')
        verbose_name_plural = _('共享笔记')
        db_table = 'shared_note'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['shared_by', '-created_at']),
            models.Index(fields=['share_token']),
            models.Index(fields=['scope', 'is_active']),
            models.Index(fields=['expires_at']),
        ]
    
    def __str__(self):
        """返回共享笔记的字符串表示"""
        return f"{self.title} - {self.share_token}"
    
    def save(self, *args, **kwargs):
        """保存时自动生成分享令牌"""
        if not self.share_token:
            self.share_token = secrets.token_urlsafe(16)
        
        # 如果没有设置标题，使用笔记标题
        if not self.title and self.note:
            self.title = self.note.title
        
        super().save(*args, **kwargs)
    
    @property
    def is_expired(self):
        """检查分享是否已过期"""
        if self.expires_at:
            return timezone.now() > self.expires_at
        return False
    
    @property
    def is_view_limit_reached(self):
        """检查是否达到访问次数限制"""
        if self.max_views:
            return self.view_count >= self.max_views
        return False
    
    @property
    def is_accessible(self):
        """检查分享是否可访问"""
        return (
            self.is_active and 
            not self.is_expired and 
            not self.is_view_limit_reached
        )
    
    def get_share_url(self):
        """获取分享链接"""
        from django.conf import settings
        base_url = getattr(settings, 'FRONTEND_URL', 'http://localhost:3000')
        return f"{base_url}/share/{self.share_token}"


class ShareAccess(models.Model):
    """分享访问记录模型
    
    记录分享笔记的访问历史。
    """
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('访问记录ID')
    )
    
    shared_note = models.ForeignKey(
        SharedNote,
        on_delete=models.CASCADE,
        related_name='access_logs',
        verbose_name=_('共享笔记')
    )
    
    # 访问者信息
    visitor = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='share_visits',
        verbose_name=_('访问者')
    )
    
    # 访问信息
    ip_address = models.GenericIPAddressField(
        _('IP地址'),
        help_text=_('访问者的IP地址')
    )
    
    user_agent = models.TextField(
        _('用户代理'),
        help_text=_('访问者的浏览器信息')
    )
    
    referrer = models.URLField(
        _('来源页面'),
        blank=True,
        help_text=_('访问的来源页面')
    )
    
    # 访问行为
    action = models.CharField(
        _('访问行为'),
        max_length=20,
        choices=[
            ('view', _('查看')),
            ('download', _('下载')),
            ('comment', _('评论')),
            ('edit', _('编辑')),
        ],
        default='view',
        help_text=_('访问者的行为类型')
    )
    
    # 会话信息
    session_id = models.CharField(
        _('会话ID'),
        max_length=40,
        help_text=_('访问会话的唯一标识')
    )
    
    duration = models.PositiveIntegerField(
        _('停留时间'),
        null=True,
        blank=True,
        help_text=_('在页面停留的时间（秒）')
    )
    
    # 时间字段
    accessed_at = models.DateTimeField(
        _('访问时间'),
        auto_now_add=True
    )
    
    class Meta:
        verbose_name = _('分享访问记录')
        verbose_name_plural = _('分享访问记录')
        db_table = 'share_access'
        ordering = ['-accessed_at']
        indexes = [
            models.Index(fields=['shared_note', '-accessed_at']),
            models.Index(fields=['visitor', '-accessed_at']),
            models.Index(fields=['ip_address']),
            models.Index(fields=['session_id']),
        ]
    
    def __str__(self):
        """返回访问记录的字符串表示"""
        visitor_name = self.visitor.username if self.visitor else '匿名用户'
        return f"{visitor_name} 访问 {self.shared_note.title}"


class ShareComment(models.Model):
    """分享评论模型
    
    用户对分享笔记的评论。
    """
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('评论ID')
    )
    
    shared_note = models.ForeignKey(
        SharedNote,
        on_delete=models.CASCADE,
        related_name='comments',
        verbose_name=_('共享笔记')
    )
    
    # 评论者
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='share_comments',
        verbose_name=_('评论者')
    )
    
    # 评论内容
    content = models.TextField(
        _('评论内容'),
        validators=[MinLengthValidator(1)],
        help_text=_('评论的具体内容')
    )
    
    # 回复关系
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='replies',
        verbose_name=_('父评论')
    )
    
    # 状态
    is_approved = models.BooleanField(
        _('已审核'),
        default=True,
        help_text=_('评论是否已通过审核')
    )
    
    is_deleted = models.BooleanField(
        _('已删除'),
        default=False,
        help_text=_('评论是否已被删除')
    )
    
    # 统计信息
    like_count = models.PositiveIntegerField(
        _('点赞数'),
        default=0,
        help_text=_('评论获得的点赞数')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    updated_at = models.DateTimeField(
        _('更新时间'),
        auto_now=True
    )
    
    class Meta:
        verbose_name = _('分享评论')
        verbose_name_plural = _('分享评论')
        db_table = 'share_comment'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['shared_note', '-created_at']),
            models.Index(fields=['author', '-created_at']),
            models.Index(fields=['parent']),
            models.Index(fields=['is_approved', 'is_deleted']),
        ]
    
    def __str__(self):
        """返回评论的字符串表示"""
        content_preview = self.content[:50] + '...' if len(self.content) > 50 else self.content
        return f"{self.author.username}: {content_preview}"
    
    @property
    def is_reply(self):
        """检查是否为回复评论"""
        return self.parent is not None
    
    @property
    def reply_count(self):
        """获取回复数量"""
        return self.replies.filter(is_deleted=False, is_approved=True).count()


class CommentLike(models.Model):
    """评论点赞模型
    
    记录用户对评论的点赞。
    """
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('点赞ID')
    )
    
    comment = models.ForeignKey(
        ShareComment,
        on_delete=models.CASCADE,
        related_name='likes',
        verbose_name=_('评论')
    )
    
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='comment_likes',
        verbose_name=_('用户')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    class Meta:
        verbose_name = _('评论点赞')
        verbose_name_plural = _('评论点赞')
        db_table = 'comment_like'
        unique_together = [['comment', 'user']]
        indexes = [
            models.Index(fields=['comment', 'user']),
            models.Index(fields=['user', '-created_at']),
        ]
    
    def __str__(self):
        """返回点赞的字符串表示"""
        return f"{self.user.username} 点赞了评论"


class SharePermission(models.Model):
    """分享权限模型
    
    管理特定用户对分享笔记的权限。
    """
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('权限ID')
    )
    
    shared_note = models.ForeignKey(
        SharedNote,
        on_delete=models.CASCADE,
        related_name='permissions',
        verbose_name=_('共享笔记')
    )
    
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='share_permissions',
        verbose_name=_('用户')
    )
    
    permission = models.CharField(
        _('权限级别'),
        max_length=20,
        choices=SharedNote.PERMISSION_CHOICES,
        default='view',
        help_text=_('用户的权限级别')
    )
    
    # 授权者
    granted_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='granted_permissions',
        verbose_name=_('授权者')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    updated_at = models.DateTimeField(
        _('更新时间'),
        auto_now=True
    )
    
    class Meta:
        verbose_name = _('分享权限')
        verbose_name_plural = _('分享权限')
        db_table = 'share_permission'
        unique_together = [['shared_note', 'user']]
        indexes = [
            models.Index(fields=['shared_note', 'user']),
            models.Index(fields=['user', 'permission']),
            models.Index(fields=['granted_by', '-created_at']),
        ]
    
    def __str__(self):
        """返回权限的字符串表示"""
        return f"{self.user.username} - {self.get_permission_display()}"
